#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include "Channel.hpp"
#include <vector>
#include "Task.hpp"
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>

void Usage()
{
    printf("erroe use argc, the num must be two\n");
}
void Worker(int td)
{
    tm.Execute(td);
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage();
        return 1;
    }
    int pipenum = std::stoi(argv[1]); // stoi把字符串转为整形，这里默认只有数字
    std::vector<Channel> channels;
    // 创建管道
    for (int i = 0; i < pipenum; i++)
    {
        int fds[2] = {0};
        int n = pipe(fds);
        if (n < 0)
        {
            printf("create pipe error!\n");
            return 2;
        }
        // 创建子进程
        pid_t id = fork();
        if (id == 0)
        {
            // 子进程 read
            close(fds[1]);
            dup2(fds[0], 0); // 让每一个子进程从标准输入读取
            while (true)
            {
                int task_id = 0;
                int n = ::read(0, &task_id, sizeof(task_id));
                if (n > 0)
                {
                    Worker(task_id);
                }
                else if (n == 0)
                    break;
                sleep(1);
            }
        }
        else
        {
            // 父进程 write - 派发任务
            close(fds[0]);
            // 保存每一与子进程通信的写端 - 先描述再组织
            channels.emplace_back(fds[1], id);
        }
    }
    // 创建任务
    int i = 0;
    srand(time(0));
    int cnt = 10;
    while (cnt--)
    {
        // 选择任务
        int td = rand() % tasknum; // 随机选择一个任务
        // 选择一个子进程
        //  分配任务 - 轮询
        // 执行任务
        ::write(channels[i].ID(), &td, sizeof(int));
        std::cout << "##########################" << std::endl;
        std::cout << "write fd : " << channels[i].ID() << " pid: " << channels[i].Pid() << std::endl;
        std::cout << "##########################" << std::endl;
        i = (i + 1) % channels.size();
        sleep(1);
    }

    for (auto& c: channels) 
    {
        close(c.ID());
    }
    for (auto& c : channels)
    {
        int wid = waitpid(c.Pid(),nullptr,0);
        if (wid < 0) 
        {
            std::cout << " wait false!!!" << std::endl; 
            exit(1);
        }
        std:: cout << " wait successful, pid: " << c.Pid() << std::endl; 
    }
    return 0;
}